<template>
	<!-- 聊天消息内容 -->
	<view class="container" id="container">
		<uni-nav-bar id="navbar" class="ch-nav" height="88rpx" backgroundColor="#ffffff" leftWidth="90rpx" rightWidth="90rpx" color="#333" :fixed="true" :padding="false" :border="true" @clickLeft="$goBack(1)">
			<template slot="left">
				<image class="left" src="@/public/images/public/dhl_fhjt.png" mode="aspectFit"></image>
			</template>
			<text class="title">{{title}}</text>
		</uni-nav-bar>
		<scroll-view 
			id="scroll" 
			ref="chatbox" 
			class="scroll-view" 
			:scroll-y="true" 
			:scroll-into-view="endView" 
			:style="scrollHeight" 
			:class="{'other': isOther, 'face': isFace}" 
			@scrolltoupper="getMoreMsg" 
		>
			<view class="loading" v-if="refreshing">
				<uni-load-more status="loading"></uni-load-more>
			</view>
			<view class="body flex-c" @tap="bodyTap">
				<view class="chat-item flex-c" :key="index" v-for="(msg, index) in messageLists" v-if="!msg.isDeleted">
					<view class="time flex-r" v-if="index == 0 || msg.time - messageLists[index-1].time > 600 || messageLists[index-1].isDeleted">
						<uni-dateformat class="color-grey" :date="msg.time*1000" format="MM月dd日 hh:mm"></uni-dateformat>
					</view>
					<view class="revoked flex-r" :id="'end-msg-' + index" v-if="msg.isRevoked">
						<template v-if="msg.flow == 'out'">
							<text class="color-grey">您撤回了一条消息</text>
							<text class="remodify color-blue" v-if="msg.type == 'TIMTextElem' && revokedMsg == msg.ID" @tap="reModify(msg)">重新编辑</text>
						</template>
						<template v-else>
							<text class="color-grey">对方撤回了一条消息</text>
						</template>
					</view>
					<view class="item flex-r" :class="{'me': msg.flow == 'out'}" :id="'end-msg-' + index" v-else>
						<view class="left border-round">
							<view class="inheritwh" @tap="$CHS.goExpertHome(msg.from, msg.flow=='in' ? 'expert' : 'user')">
								<lazy-image class="inheritwh border-round" :src="msg.avatar+'?imageView2/1/w/100/h/100/q/50'" :type="msg.flow=='in' ? 'expert' : 'user'" fit="cover"></lazy-image>
							</view>
						</view>
						<view class="right flex-c" @touchmove="msgTouchMove" @touchend="msgTouchEnd">
							<template v-if="msg.type == 'TIMTextElem'">
								<view class="text" @longpress="onLongPress(msg, $event)">
									<rich-text :nodes="parseTextMsg(msg)" space="nbsp" :selectable="true" @itemclick="msgClick"></rich-text>
									<!-- text v-html="parseTextMsg(msg)" space="nbsp" :selectable="true" @itemclick="msgClick"></text -->
									<!-- template v-for="(item,index) in parseTextMsg(msg)">
										<span v-if="item.name != 'img'" :key="index" v-html="item.text" @longpress="onLongPress(item.text, $event)" :selectable="true"></span>
										<img v-else class="face-message" :key="index" :src="item.src" style="width: 42rpx;height: 42rpx;object-fit: cover;" />
									</template -->
								</view>
							</template>
							<template v-else-if="msg.type == 'TIMImageElem'">
								<view class="image" @tap="previewImage(msg.payload.imageInfoArray[0].url)" @longpress="onLongPress(msg, $event)">
									<image :src="msg.payload.imageInfoArray[1].url" mode="widthFix" style="max-width: 450rpx;" :style="{'width': msg.payload.imageInfoArray[1].width + 'rpx'}"></image>
								</view>
							</template>
							<template v-else-if="msg.type == 'TIMFaceElem'">
								<view class="image" @longpress="onLongPress(msg, $event)">
									<image :src="require('@/public/images/emoji/ch-customface/ch_emoji_'+msg.payload.index+'@2x.png')" mode="widthFix" style="max-width: 240rpx;"></image>
								</view>
							</template>
							<template v-else-if="msg.type == 'TIMSoundElem'">
								<view class="text sound flex-r" @tap="playSound(msg.payload, index)" @longpress="onLongPress(msg, $event)">
									<template v-if="msg.flow=='in'">
										<view class="sound-icon" :class="{'playing': index == isPlaying}"></view>
										<text style="max-width: 360rpx;min-width: 40rpx;" :style="'width:'+ (msg.payload.second / 60 * 360 ) +'rpx'">{{msg.payload.second || 1}}″</text>
									</template>
									<template v-else>
										<text style="max-width: 360rpx;min-width: 40rpx;text-align: right;" :style="'width:'+ (msg.payload.second / 60 * 360 ) +'rpx'">{{msg.payload.second || 1}}″</text>
										<view class="sound-icon" :class="{'playing': index == isPlaying}"></view>
									</template>
								</view>
							</template>
							<template v-else-if="msg.type == 'TIMVideoFileElem'">
								<view class="video" @longpress="onLongPress(msg, $event)">
									<FullVideo :url="msg.payload.videoUrl" :poster="msg.payload.snapshotUrl" :width="msg.payload.snapshotWidth + 'rpx'" :height="msg.payload.snapshotHeight + 'rpx'"></FullVideo>
								</view>
							</template>
							<template v-else-if="msg.type == 'TIMCustomElem' && JSON.parse(msg.payload.data).businessID == 'custom_message_imageType'">
								<view class="image" @tap="previewImage(msg.payload)" @longpress="onLongPress(msg, $event)">
									<lazy-image :src="JSON.parse(msg.payload.data).imageUrl" fit="cover" style="max-width: 450rpx;" error="@/public/images/public/error.png"></lazy-image>
								</view>
							</template>
							<template v-else-if="msg.type == 'TIMCustomElem'">
								<view class="custom" @longpress="onLongPress(msg, $event)">
									<CustomMessage :message="msg.payload.data"></CustomMessage>
								</view>
							</template>
							<text v-if="msg.flow=='out'" class="status">{{msg.isPeerRead ? '已读' : '未读'}}</text>
						</view>
					</view>
				</view>
			</view>
		</scroll-view>
		<view class="foot" id="footer">
			<view class="input-box flex-r">
				<image src="@/public/images/message/audio.png" class="icon" mode="aspectFit" @tap="sendAudioMsg"></image>
				<textarea 
					v-if="isSafariBrowser"
					v-model="textMsg"
					ref="inputBox"
					class="textarea" 
					:auto-height="true" 
					:auto-blur="true" 
					:fixed="true" 
					maxlength="-1" 
					confirm-type="send" 
					@focus="focus" 
					@blur="blur" 
					@linechange="linechange"
					@confirm.prevent="sendTextMsg()"></textarea>
				<div
					v-else
				    ref="inputBox"
				    class="textarea"
				    contenteditable="true"
					enterkeyhint="send" 
					confirm-type="send"
					@input="change()" 
					@focus="focus" 
					@blur="blur" 
					@confirm.prevent="sendTextMsg()"
					@keyup.13="sendTextMsg()"></div>
				<image src="@/public/images/message/bq.png" class="icon mr25" mode="aspectFit" v-show="!isFace" @tap="inputFace"></image>
				<image src="@/public/images/message/jp.png" class="icon mr25" mode="aspectFit" v-show="isFace" @tap="inputFace"></image>
				<image src="@/public/images/message/gd.png" class="icon" mode="aspectFit" @tap="inputOther" v-if="!sendBtn"></image>
				<button type="default" size="mini" class="btn" @touchend.prevent="sendTextMsg" v-else-if="isMobile">发送</button>
				<button type="default" size="mini" class="btn" @tap="sendTextMsg" v-else-if="!isMobile">发送</button>
			</view>
			<keep-alive>
			<view class="other-box flex-r" v-if="isOther">
				<view class="other-item flex-c" @tap="chooseImg">
					<image src="@/public/images/message/tp.png" mode="aspectFit"></image>
					<text>图片</text>
				</view>
			</view>
			</keep-alive>
			<keep-alive>
			<view class="face-box flex-r" v-if="isFace">
				<TUI-Emoji @enterEmoji="appendMessage"></TUI-Emoji>
				<image class="delete" @tap="deleteFaceImg()" src="@/public/images/components/srf_qx.png" mode="aspectFit"></image>
			</view>
			</keep-alive>
		</view>
		<view class="full-screen" v-if="isPreview" @touchstart="touchStart" @touchend="touchEnd" @tap="canclePreview">
			<movable-area>
				<movable-view class="pic" direction="all" :out-of-bounds="true" scale="true" scale-min="0.5" scale-max="4" @longtap="longtap($event)" @change="moveChange">
					<image class="img" :src="previewImageSrc" mode="widthFix"></image>
				</movable-view>
			</movable-area>
			<view class="cropper-wrap-tools" v-if="selectImg">
				<view class="cropper-wraper-cancel" @tap.stop="selectImg = null;isPreview = false">取消</view>
				<view class="cropper-wraper-confirm" @tap.stop="confirmSendImage(selectImg)">发送</view>
			</view>
		</view>
		<view class="shade" v-show="showShade" @tap="hidePop">
			<view class="pop" :style="popStyle" :class="{'show':showPop}" v-if="selectMsg !== null">
				<view v-if="selectMsg.type == 'TIMTextElem'" @tap="copyMessage(selectMsg)">复制内容</view>
				<view v-if="selectMsg.flow == 'out'" @tap="revokeMessage(selectMsg)">撤回消息</view>
				<view @tap="delMessage(selectMsg)">删除消息</view>
			</view>
		</view>
	</view>
</template>

<script>
	import imMsg from "@/utils/common/message.js";
	import * as qiniu from 'qiniu-js'
	import {parseText} from "./components/tim-emoji/message-facade.js";
	import { emojiUrl, emojiMap } from './components/tim-emoji/emojiMap.js';
	import jsQrDecode from "@/utils/common/jsQR.js"
	const TIM = imMsg.TIM
	const tim = imMsg.tim()
	export default {
		data() {
			return {
				title: '聊天消息', //聊天框标题
				sendBtn: false, //发送按钮状态
				isFace: false, //发送表情状态
				isOther: false, //更多按钮状态
				toUserId: null, //接收用户ID
				textMsg: '', //文字消息内容
				selectImg: null, //已选图片
				isSending: false, //发送中
				chatId: null, //对话ID
				messageLists: null, //消息列表
				nextReqMessageID: null, //加载更多消息时使用的下一条消息ID
				isCompleted: false, //是否已全部加载完
				endView: '', //滚动位置
				innerAudioContext: null, //音频对象，用于播放语音
				onMessageReceived: null, //收到消息事件回调
				textHeight: 0, //聊天框内文字高度
				footHeight: 96, //底部输入框初始高度
				KeyboardHeight: 0, //键盘高度
				windowHeight: 0, //窗口可用高度
				domainUrl: null, //七牛云链接域名
				token: null, //七牛token
				isSafariBrowser: true, //Safari浏览器
				previewImageSrc: '', //预览图片src
				previewImageList: null, //预览图片列表
				isPreview: false, //预览状态
				isPlaying: null, //音频播放状态

				winSize: {}, //窗口尺寸
				showShade: false, //展示弹窗菜单
				showPop: false, //弹窗动画效果
				popStyle: "", //弹窗位置
				selectMsg: null, //已选择的消息
				revokedMsg: null, //当前撤回消息的ID

				refreshing: false //刷新状态
			}
		},
		components: {
			TUIEmoji: () => import('./components/tim-emoji/emoji.vue'),
			CustomMessage: () => import('./components/ch-message/ch-custommessage.vue')
		},
		computed: {
			user() {
				return this.$store.state.user
			},
			imReady() {
				return this.$store.state.imReady
			},
			scrollHeight() {
				if(this.windowHeight){
					return `height:calc(${this.windowHeight}px - ${this.footHeight + this.textHeight}rpx - var(--navbar-height) - ${this.KeyboardHeight}px);`;
				}else{
					return `height:calc(var(--safe-height) - ${this.footHeight + this.textHeight}rpx - var(--navbar-height) - ${this.KeyboardHeight}px);`;
				}
			},
			isMobile(){
				if(window.navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i)) {
					return true
				}else{
					return false
				}
			}
		},
		watch: {
			messageLists(newValue, oldValue) {
				this.upScrollView()
			},
			imReady(newValue, oldValue) {
				if(newValue){
					this.chatInit()
				}
			},
			textMsg(newValue, oldValue) {
				console.log(newValue);
				this.sendBtn = newValue !== ''
				if(newValue == '' && !this.isSafariBrowser){
					this.$refs.inputBox.innerHTML = ''
				}
				setTimeout(()=>{
					uni.createSelectorQuery().select('.input-box').boundingClientRect(data => {
						console.log(data);
						let rpx = 750 / data.width //设计稿宽度750 / 实际渲染宽度 = 缩放比例
						this.textHeight = data.height * rpx - 96 //计算输入框的新增高度
						this.upScrollView()
					}).exec()
				}, 10)
			}
		},
		onLoad() {
			let osName = uni.getSystemInfoSync().osName
			this.isSafariBrowser = osName.includes('ios') || osName.includes('macos')
			//收到消息监听
			let that = this
			const onMessageReceived = function(imResponse) {
				console.log(imResponse.data);
				if(imResponse.data[0].conversationID == that.chatId){
					imResponse.data.forEach( (item) => {
						if(that.messageLists){
							that.messageLists.push(item)
						}else{
							that.messageLists[0] = item
						}
					})
					//全部已读
					tim.setMessageRead({conversationID: imResponse.data[0].conversationID});
				}
			};
			this.onMessageReceived = onMessageReceived
			tim.on(TIM.EVENT.MESSAGE_RECEIVED, this.onMessageReceived);
			//会话ID
			if(this.$Route.query.cid){
				this.chatId = this.$Route.query.cid
				this.toUserId = this.$Route.query.cid.substr(3)
				console.log(this.toUserId);
				if(this.imReady){
					this.chatInit()
				}
				this.$store.commit("SET_CHATID", this.chatId)
			}else{
				this.$goBack(1)
				return
			}
			//延迟更新聊天框滚动位置
			setTimeout(()=>{
				this.upScrollView()
			}, 500)
		},
		onShow() {
			uni.onWindowResize((res) => {
				this.KeyboardHeight = this.windowHeight - res.size.windowHeight
				this.upScrollView()
			})
		},
		onReady() {
			let sys = uni.getSystemInfoSync()
			this.windowHeight = sys.windowHeight - sys.safeAreaInsets.bottom
			this.winSize = {
				"witdh": sys.windowWidth,
				"height": sys.windowHeight
			}
			window.addEventListener('contextmenu', function(e){
				e.preventDefault();
				return false;
			});
		},
		mounted() {
			this.chatId = this.$Route.query.cid
			if(!this.isSafariBrowser){
				this.$refs.inputBox.focus()
				this.$nextTick(()=>{
					this.$refs.inputBox.blur()
				})
			}
			let drafts = uni.getStorageSync(this.chatId+'_msg_drafts')
			if(drafts){
				this.textMsg = drafts
				if(!this.isSafariBrowser){
					let html = uni.getStorageSync(this.chatId+'_msg_drafts_html')
					this.$refs.inputBox.innerHTML = html
					this.change()
					this.$nextTick(()=>{
						this.keepLastIndex()
					})
				}
			}
		},
		updated() {
			this.endView = ''
		},
		onHide() {
			uni.offWindowResize(() => {})
		},
		onUnload() {
			this.$store.commit("SET_CHATID", null)
			if(this.onMessageReceived){
				tim.off(TIM.EVENT.MESSAGE_RECEIVED, this.onMessageReceived);
			}
			if(this.textMsg){
				uni.setStorageSync(this.chatId+'_msg_drafts', this.textMsg)
				if(!this.isSafariBrowser){
					uni.setStorageSync(this.chatId+'_msg_drafts_html', this.$refs.inputBox.innerHTML)
				}
			}else{
				uni.removeStorageSync(this.chatId+'_msg_drafts', this.textMsg)
				if(!this.isSafariBrowser){
					uni.removeStorageSync(this.chatId+'_msg_drafts_html', this.$refs.inputBox.innerHTML)
				}
			}
		},
		beforeRouteLeave(to, from, next) {
			if(this.isPreview){
				this.isPreview = false
				this.selectImg = null
				next(false);
			}else{
				next();
			}
		},
		methods: {
			//聊天初始化
			chatInit() {
				this.getMsgInfo(this.chatId)
				this.getMsgInfoList(this.chatId)
				//全部已读
				tim.setMessageRead({conversationID: this.chatId});
			},
			//会话资料
			getMsgInfo(chatId) {
				imMsg.getMsgInfo(chatId).then((imResponse) => {
					//console.log(imResponse.data.conversation); // 会话资料
					this.toUserId = imResponse.data.conversation.userProfile.userID
					this.title = imResponse.data.conversation.userProfile.nick
				}).catch((imError)=>{
					console.log(imError);
					uni.showToast({
						title: imError.message,
						icon: 'none'
					})
				})
			},
			//会话消息列表
			getMsgInfoList(chatId) {
				if(this.imReady){
					imMsg.getMsgInfoList(chatId).then((imResponse)=>{
						console.log(imResponse.data.messageList);
						this.messageLists = imResponse.data.messageList
						this.nextReqMessageID = imResponse.data.nextReqMessageID
						this.isCompleted = imResponse.data.isCompleted
					}).catch((imError)=>{
						console.log(imError);
					})
				}else{
					uni.showToast({
						title: '消息加载错误，请稍候重试',
						icon: 'none'
					})
				}
			},
			//加载更多
			getMoreMsg(){
				if(this.imReady){
					this.refreshing = true
					if(!this.isCompleted){
						imMsg.getMsgInfoList(this.chatId, this.nextReqMessageID).then((imResponse)=>{
							console.log(imResponse.data.messageList);
							this.isMore = true
							this.nowIndex = imResponse.data.messageList.length
							this.messageLists.unshift(...imResponse.data.messageList)
							this.nextReqMessageID = imResponse.data.nextReqMessageID
							this.isCompleted = imResponse.data.isCompleted
							this.refreshing = false
						}).catch((imError)=>{
							console.log(imError);
							this.refreshing = false
						})
					}else{
						this.refreshing = false
					}
				}else{
					this.$ShowToast({text: '您的账号已离线，请刷新网页', type: 2, time: 3})
				}
			},
			//消息长按监听
			onLongPress(msg, e) {
				console.log(msg);
				if(this.canLongtap){//可以长按唤出菜单
					this.selectMsg = msg
					let [touches, style] = [e.touches[0], ""];
					
					if (touches.clientY > (this.winSize.height / 2)) {
						style = `bottom:${this.winSize.height-touches.clientY}px;`;
					} else {
						style = `top:${touches.clientY}px;`;
					}
					if (touches.clientX > (this.winSize.witdh / 2)) {
						style += `right:${this.winSize.witdh-touches.clientX}px`;
					} else {
						style += `left:${touches.clientX}px`;
					}
					
					this.popStyle = style;
					this.showShade = true;
					this.$nextTick(() => {
						setTimeout(() => {
							this.showPop = true;
						}, 10);
					});
					e.preventDefault();
					return false;
				}
			},
			//复制文字
			copyMessage(msg) {
				uni.setClipboardData({
					data: msg.payload.text,
					success() {
						uni.showToast({
							title:'内容已复制',
							icon: 'success'
						})
					}
				})
			},
			//撤回消息
			revokeMessage(msg) {
				console.log(msg);
				if(this.imReady){
					imMsg.revokeMessage(msg).then((imResponse)=>{
						console.log(imResponse.data);
						this.revokedMsg = imResponse.data.message.ID
						uni.showToast({
							title: '消息撤回成功',
							icon: 'success'
						})
					}).catch((imError)=>{
						console.log(imError);
						if(imError.code == '20016'){
							uni.showToast({
								title: '消息撤回已超时',
								icon: 'none'
							})
						}else{
							uni.showToast({
								title: '消息撤回失败',
								icon: 'none'
							})
						}
					})
				}else{
					uni.showToast({
						title: '您的账号已离线',
						icon: 'none'
					})
				}
			},
			//撤回消息重新编辑
			reModify(message){
				console.log(message);
				if(this.isSafariBrowser){
					this.textMsg = message.payload.text
				}else{
					this.textMsg = message.payload.text
					let content = {
						type: 'TIMTextElem',
						payload: {
							text: this.textMsg
						}
					}
					let msgArr = parseText(content)
					console.log(msgArr);
					let html = ''
					for(let item of msgArr){
						if(item.name != 'img'){
							html += item.text
						}else{
							html += '<img class="face-message" style="width:14%" src="'+item.src+'"/>'
						}
					}
					console.log(html);
					this.$refs.inputBox.innerHTML = html
				}
			},
			//删除消息
			delMessage(msg) {
				if(this.imReady){
					imMsg.deleteMessage([msg]).then((imResponse)=>{
						console.log(imResponse.data);
						uni.showToast({
							title: '消息已删除',
							icon: 'success'
						})
					}).catch((imError)=>{
						console.log(imError);
						uni.showToast({
							title: '操作失败，请重试',
							icon: 'none'
						})
					})
				}else{
					uni.showToast({
						title: '您的账号已离线',
						icon: 'none'
					})
				}
			},
			//消息触摸结束
			msgTouchEnd() {
				this.canLongtap = true; //可以长按唤出菜单
			},
			//消息触摸滑动
			msgTouchMove() {
				//防止滑动时触发长按菜单
				this.canLongtap = false; //不可以长按唤出菜单
			},
			//隐藏弹窗
			hidePop() {
				this.showPop = false;
				setTimeout(() => {
					this.showShade = false;
				}, 250);
			},
			//点击消息超链接
			msgClick(e) {
				console.log(e.detail.node);
				if(e.detail.node.name == 'a'){
					let href = e.detail.node.attrs.href
					if(href.includes(this.$CHS.config.hostUrl)){
						window.open(href, "_blank")
					}else{
						uni.showToast({
							title: '不支持打开外部链接',
							icon: 'none'
						})
					}
				}
			},
			//触摸非输入区域隐藏底部工具
			bodyTap() {
				this.isFace = false
				this.isOther = false
				this.footHeight = 96
			},
			//输入聚焦
			focus(e) {
				console.log(e);
				this.isFace = false
				this.isOther = false
				this.footHeight = 96
				setTimeout(() => {
					if(!this.isSafariBrowser){
						let sys = uni.getSystemInfoSync()
						this.KeyboardHeight = this.windowHeight - ( sys.windowHeight - sys.safeAreaInsets.bottom )
						this.upScrollView()
					}else{
						this.upScrollView()
					}
				}, 500)
			},
			//输入框失焦
			blur() {
				this.KeyboardHeight = 0
			},
			//输入内容变化
			change() {
				let html = this.$refs.inputBox.innerHTML
				html = html.replace(/&nbsp;/ig, ' ');
				html = html.replace(/<div><br><\/div>/ig, "\n");
				html = html.trim()
				if(/<img/.test(html)){
					let imgReg = /<img.*?(?:>|\/>)/gi //匹配图片
					let indexReg = /emoji_([0-9]+)@2x\.png/i //匹配表情索引
					let result = html.match(imgReg);
					for (let i = 0; i < result.length; i++) {
						let src = result[i].match(indexReg);
						if(src[1]){
							html = html.replace(result[i], Object.keys(emojiMap)[src[1]]);
						}
					}
					console.log(html);
				}
				this.textMsg = html
			},
			//添加表情消息
			appendMessage(e) {
				console.log(e.detail.message);
				if(this.isSafariBrowser){//Safari浏览器
					this.textMsg = this.textMsg + e.detail.message
				}else{
					let src = emojiUrl + emojiMap[e.detail.message]
					let obj = this.$refs.inputBox
					if (window.getSelection) {
						let selection = window.getSelection()
						let range = selection.getRangeAt(0); //创建range
						let html = '<img class="face-message" style="width:14%" src="'+src+'"/>'
						let node = range.createContextualFragment(html);
						range.insertNode(node);
						obj.setAttribute("contenteditable", false) //避免触发键盘弹出
						selection.collapse(obj, range.endOffset); //光标移至最后
						setTimeout(()=>{
							obj.setAttribute("contenteditable", true) //恢复可编辑状态
						}, 50)
						this.change()
					}else{
						this.textMsg = this.textMsg + e.detail.message
					}
				}
			},
			//删除表情图片
			deleteFaceImg() {
				let htmlMsg = ''
				if(this.textMsg.endsWith(']')){
					let index = this.textMsg.lastIndexOf('[')
					if(index > -1){
						htmlMsg = this.textMsg.substr(0, index)
					}else{
						htmlMsg = this.textMsg.substr(0, this.textMsg.length - 1)
					}
				}else{
					htmlMsg = this.textMsg.substr(0, this.textMsg.length - 1)
				}
				this.textMsg = htmlMsg
				if(this.isSafariBrowser){
					return
				}
				let content = {
					type: 'TIMTextElem',
					payload: {
						text: this.textMsg
					}
				}
				let msg = parseText(content)
				console.log(msg);
				let html = ''
				msg.forEach((item)=>{
					if(item.name != 'img'){
						html += item.text
					}else{
						html += '<img class="face-message" style="width:14%" src="'+item.src+'"/>'
					}
				})
				this.$refs.inputBox.innerHTML = html
			},
			//输入框输入内容行数变化回调
			linechange(e) {
				console.log(e.detail);
				if(e.detail.lineCount < 8){
					this.textHeight = e.detail.heightRpx - 52
				}else{
					this.textHeight = e.detail.heightRpx/e.detail.lineCount * 7 - 52
				}
				this.upScrollView()
			},
			//光标位置移至最后
			keepLastIndex() {
				let obj = this.$refs.inputBox
				console.log(obj);
				if (window.getSelection) { //ie11 10 9 ff safari
					if(!this.isSafariBrowser){
						obj.focus(); //解决ff不获取焦点无法定位问题
					}
					let range = window.getSelection(); //创建range
					range.selectAllChildren(obj); //range 选择obj下所有子内容
					range.collapseToEnd(); //光标移至最后
				} else if (document.selection) { //ie10 9 8 7 6 5
					let range = document.selection.createRange(); //创建选择对象
					range.moveToElementText(obj); //range定位到obj
					range.collapse(false); //光标移至最后
					range.select();
				}
			},
			//发送其他
			inputOther() {
				this.isFace = false
				this.isOther = ! this.isOther
				this.footHeight = this.isOther ? 296 : 96
				this.KeyboardHeight = 0
				this.upScrollView()
			},
			//发送表情
			inputFace() {
				this.isOther = false
				this.isFace = !this.isFace
				this.footHeight = this.isFace ? 576 : 96
				this.KeyboardHeight = 0
				this.upScrollView()
			},
			//更新scrollview聊天滚动位置
			upScrollView(){
				if(this.messageLists){
					let index = 0
					if(!this.isMore){
						index = this.messageLists.length-1
					} else {
						index = this.nowIndex
					}
					this.$nextTick(()=>{
						console.log('end-msg-' + index);
						this.endView = 'end-msg-' + index
						this.isMore = false
					})
				}
			},
			//解析表情信息
			parseTextMsg(messsage) {
				let msgArr = parseText(messsage)
				let html = ''
				for(let item of msgArr){
					if(item.name != 'img'){
						//JS 正则匹配 URL
						var regexp = /((http|https):\/\/([\w\-]+\.)+[\w\-]+(\/[\w\u4e00-\u9fa5\-\.\/?\@\%\!\&=\+\~\:\#\;\,]*)?)/ig;
						var urls = item.text.match(regexp);
						if (urls && typeof(urls) != undefined){
							urls = [...new Set(urls)];
							urls.forEach((url)=>{
								let str = '<a href="'+url+'">'+url+'</a>'
								let reg = new RegExp(url, "g")
								item.text = item.text.replace(reg, str)
							})
						}
						html += '<span>'+item.text+'</span>'
					}else{
						html += '<img class="face-message" src="'+item.src+'"/>'
					}
				}
				return html
			},
			//发送文本消息
			sendTextMsg() {
				if(!this.imReady){
					this.$ShowToast({text: '您的账号已离线，请刷新网页', type: 2})
					return
				}
				if(this.textMsg && this.toUserId && !this.isSending){
					this.isSending = true
					this.saveMsg(this.textMsg, "TIMTextElem").then((data)=>{
						if(data.success){
							imMsg.sendTextMsg(this.toUserId, this.textMsg).then((imResponse) => {
								console.log(imResponse.data.message);
								this.textMsg = ''
								this.chatId = imResponse.data.message.conversationID
								if(this.messageLists){
									this.messageLists.push(imResponse.data.message)
								}else{
									this.messageLists[0] = imResponse.data.message
								}
								this.isSending = false
							}).catch((imError)=>{
								console.log(imError.message);
								this.msgSendError()
							})
						}else{
							this.msgSendError(data.message)
						}
					}).catch((res)=>{
						this.msgSendError()
					})
				}else{
					this.msgSendError()
				}
			},
			//发送语音消息
			sendAudioMsg() {
				uni.showModal({
					title: '系统提示',
					content: '手机网页暂不支持发送语音', //，推荐下载彩虹体育APP使用更多功能。
					confirmText: '确定',
					success: (res) => {
						console.log(res)
						if(res.confirm){
							//this.$goByName('downapp')
						}
					}
				})
			},
			//选择发送图片
			chooseImg() {
				if(!this.imReady){
					this.$ShowToast({text: '您的账号已离线，请刷新网页', type: 2})
					return
				}
				uni.chooseImage({
					count: 1,
					sizeType: ['compressed'],
					extension: ['jpg','png'],
					success: (img) => {
						console.log(img)
						if(this.toUserId){
							this.selectImg = img
							this.isPreview = true
							this.previewImageSrc = img.tempFilePaths[0]
							this.previewImageList = img.tempFilePaths
						}else{
							this.msgSendError()
						}
					}
				});
			},
			//确定发送图片
			confirmSendImage(img){
				this.isPreview = false
				this.$CHS.getQiniuToken().then( (result)=>{
					this.token = result.token
					this.domainUrl = result.url
					this.$ShowLoading({show: true})
					this.qiniuUpload(img.tempFiles[0]).then((res)=>{
						let imgUrl = this.domainUrl + '/' + res.key
						//保存到服务器
						this.saveMsg(imgUrl, "TIMImageElem").then((data)=>{
							if(data.success){
								//this.sendImageMsg(img)
								this.sendCustomImageMsg(imgUrl)
							}else{
								this.msgSendError(data.message)
							}
						}).catch((res)=>{
							this.msgSendError()
						})
					}).catch((res)=>{
						this.msgSendError('网络异常，请重试')
					}).finally(()=>{
						this.$ShowLoading({show: false})
					})
				}).catch((res) => {
					console.log(res);
					this.msgSendError('网络异常，请重试')
				}).finally(()=>{
					this.selectImg = null
				})
			},
			//发送图片信息
			sendImageMsg(img) {
				this.$ShowLoading({show: true})
				imMsg.sendImageMsg(this.toUserId, img).then((imResponse) => {
					console.log(imResponse.data.message);
					this.bodyTap()
					this.chatId = imResponse.data.message.conversationID
					if(this.messageLists){
						this.messageLists.push(imResponse.data.message)
					}else{
						this.messageLists[0] = imResponse.data.message
					}
				}).catch((imError)=>{
					console.log(imError);
					this.msgSendError()
				}).finally(()=>{
					this.$ShowLoading({show: false})
				})
			},
			//发送自定义图片信息
			sendCustomImageMsg(imageUrl) {
				this.$ShowLoading({show: true})
				let customMsg = {
					businessID: "custom_message_imageType", //自定义图片类型
					imageUrl //图片七牛云URL
				}
				customMsg = JSON.stringify(customMsg)
				console.log(customMsg)
				imMsg.sendCustomMsg(this.toUserId, customMsg, "[图片]", "[图片]").then((imResponse) => {
					console.log(imResponse.data.message);
					this.bodyTap()
					this.chatId = imResponse.data.message.conversationID
					if(this.messageLists){
						this.messageLists.push(imResponse.data.message)
					}else{
						this.messageLists[0] = imResponse.data.message
					}
				}).catch((imError)=>{
					console.log(imError);
					this.msgSendError()
				}).finally(()=>{
					this.$ShowLoading({show: false})
				})
			},
			//消息发送失败
			msgSendError(text='发送失败') {
				uni.showToast({
					title: text,
					icon: 'none'
				})
				this.isSending = false
			},
			//保存消息到服务器
			saveMsg(content, sendType) {
				return new Promise((resolve,reject)=>{
					console.log(content);
					this.$http.post({
						url: '/api/userMessageRecord/add',
						data: {
							sendUserId: this.user.userId,
							receiveUserId: this.toUserId,
							messageId: this.chatId,
							isBatch: 0,
							sendType,
							content
						},
					}).then(data => {
						console.log(data);
						resolve(data)
					}).catch((err) => {
						console.log(err);
						reject(err)
					})
				})
			},
			//七牛上传图片
			qiniuUpload(file) {
				return new Promise((resolve,reject)=>{
					let type = file.type.substr(6)
					let key = Date.now() + 'H5.' + type
					const observer = {
						next(res){
							console.log(res);
						},
						error(err){
							console.log(err);
							reject(err)
						},
						complete(res){
							console.log(res);
							resolve(res)
						}
					}
					const options = {
						quality: 0.4,
						noCompressIfLarger: true
					}
					//压缩图片
					qiniu.compressImage(file, options).then(data => {
						const observable = qiniu.upload(data.dist, key, this.token)
						const subscription = observable.subscribe(observer) // 上传开始
					})
				})
			},
			//音频播放
			playSound(e, index) {
				if (this.isPlaying === null) {
					this.innerAudioContext = uni.createInnerAudioContext();
					this.audioPlay(e.url, index)
				} else if (this.isPlaying === index) {
					console.log('停止播放');
					this.innerAudioContext.stop()
					this.innerAudioContext.destroy()
					this.innerAudioContext = null
					this.isPlaying = null
				} else {
					this.innerAudioContext.stop()
					this.audioPlay(e.url, index)
				}
			},
			//音频播放
			audioPlay(url, index){
				this.innerAudioContext.src = url;
				this.innerAudioContext.autoplay = true;
				this.innerAudioContext.onCanplay(() => {
					console.log('可以开始播放');
					this.innerAudioContext.play()
				});
				this.innerAudioContext.onPlay(() => {
					console.log('开始播放');
					this.isPlaying = index
				});
				this.innerAudioContext.onEnded((res) => {
					console.log('结束播放');
					this.innerAudioContext.destroy()
					this.innerAudioContext = null
					this.isPlaying = null
				});
			},
			//图片预览
			previewImage(payload){
				let tempFilePaths = ''
				if(typeof payload == 'object'){
					tempFilePaths = JSON.parse(payload.data).imageUrl
				}else{
					tempFilePaths = payload
				}
				let imgList = []
				this.messageLists.forEach((item) => {
					if(item.type == 'TIMImageElem' && !item.isDeleted && !item.isRevoked){
						imgList.push(item.payload.imageInfoArray[0].url)
					}
					if(item.type == 'TIMCustomElem' && JSON.parse(item.payload.data).businessID == 'custom_message_imageType' && !item.isDeleted && !item.isRevoked){
						imgList.push(JSON.parse(item.payload.data).imageUrl)
					}
				})
				this.isPreview = true
				this.previewImageSrc = tempFilePaths
				this.previewImageList = imgList
			},
			//图片切换
			imageChange(type) {
				if(this.selectImg){
					return false
				}
				if(this.imageCanChange){
					let index = this.previewImageList.findIndex((item)=>{
						return item == this.previewImageSrc
					})
					let next = index + type
					if(next >= 0 && next < this.previewImageList.length){
						this.previewImageSrc = this.previewImageList[next]
					}else{
						uni.showToast({
							title: '已经是最后一张了',
							icon: 'none'
						})
					}
				}
			},
			//点击取消预览
			canclePreview() {
				if(this.selectImg == null){
					this.isPreview = false
				}
			},
			//图片长按识别二维码
			longtap(e) {
				console.log(e);
				e.preventDefault()
				if(this.selectImg){
					return false
				}
				//尝试识别二维码
				this.urlToFile(this.previewImageSrc, (imageData)=>{
					let qrcode = jsQrDecode(imageData.data, imageData.width, imageData.height, {
						inversionAttempts: "dontInvert",
					});
					if(qrcode && qrcode.data){
						let donate = /donate\/(.*)/i.exec(qrcode.data)
						if(donate && donate[1]){
							console.log(donate[1]);
							this.isPreview = false
							this.$goByName('expertdonate', {eid: donate[1], random: Date.now()})
						}else{
							donate = /donate_(.*)/i.exec(qrcode.data)
							if(donate && donate[1]){
								console.log(donate[1]);
								this.isPreview = false
								this.$goByName('expertdonate', {eid: donate[1], random: Date.now()})
							}else if(qrcode.data.includes(this.$CHS.config.hostUrl)){
								this.isPreview = false
								window.open(qrcode.data, "_blank")
							}
						}
					}
				})
			},
			//图片链接转File对象
			urlToFile (url, callback) {
				const image = new Image() // 初始化一个image图像
				image.crossOrigin = '*' // 这个是为了解决图片的跨域问题，有些时候不生效，则需要后端配置
				image.src = url 
				image.onload = function () { // 当然在图片加载完成后去执行以下代码
					const canvas = document.createElement('canvas') // 将image图像转化成canvas图像
					canvas.width = image.width // canvas长宽与image保持一致
					canvas.height = image.height 
					const ctx = canvas.getContext('2d')
					ctx.drawImage(image, 0, 0, image.width, image.height)
					const imageData = ctx.getImageData(0, 0, image.width, image.height)
				    callback(imageData)
				}
			},
			//触摸滑动开始
			touchStart(e) {
				console.log('start');
				if (e.changedTouches.length == 1) {
					this.startX = e.changedTouches[0].clientX
					this.startY = e.changedTouches[0].clientY
				}
			},
			//触摸滑动结束
			touchEnd(e) {
				console.log('end');
				if (e.changedTouches.length == 1) {
					var endX = e.changedTouches[0].clientX;
					var endY = e.changedTouches[0].clientY;
					var xTowards = endX - this.startX;
					var yTowards = endY - this.startY;
					if (xTowards > 50 && Math.abs(yTowards) < 50) {//向右
						console.log('向右')
						this.imageChange(-1)
					}
					if (xTowards < -50 && Math.abs(yTowards) < 50) {//向左
						console.log('向左')
						this.imageChange(1)
					}
				}
			},
			//拖动过程中触发的事件
			moveChange(event){
				console.log(event.detail);
				if(event.detail.source == 'touch'){
					this.imageCanChange = false
				}
				if(event.detail.source == 'touch-out-of-bounds'){
					this.imageCanChange = true
				}
			}
		}
	}
</script>

<style lang="scss">
	.scroll-view{
		height: calc(var(--safe-height) - #{$navbar-height} - 96rpx);
		&.other{
			height: calc(var(--safe-height) - #{$navbar-height} - 200rpx - 96rpx);
		}
		&.face{
			height: calc(var(--safe-height) - #{$navbar-height} - 480rpx - 96rpx);
		}
		.body{
			padding: 20rpx 20rpx 0;
			.chat-item{
				.time, .revoked{
					align-items: center;
					justify-content: center;
					.color-grey{
						font-size: 26rpx;
						font-family: Arial;
						line-height: 26rpx;
						margin-bottom: 40rpx;
					}
				}
				.revoked{
					text{
						font-size: 26rpx;
						font-family: Arial;
						line-height: 26rpx;
					}
					.color-blue{
						margin-left: 20rpx;
						margin-bottom: 40rpx;
					}
				}
				.item{
					align-items: flex-start;
					margin-bottom: 40rpx;
					.left{
						width: 88rpx;
						height: 88rpx;
						background-color: #FFFFFF;
						background-size: 100%;
					}
					.right{
						max-width: 532rpx;
						margin: 0 0 0 20rpx;
						align-items: center;
						.text{
							max-width: 502rpx;
							display: inline-block;
							padding: 25rpx 20rpx;
							background-color: #fff;
							border-radius: 10rpx;
							line-height: 42rpx;
							text-align: justify;
							box-sizing: border-box;
							text{
								display: inline-block;
								font-size: 28rpx;
								line-height: 42rpx;
								vertical-align:middle;
							}
							/deep/ a, span{
								word-break: break-all;
							}
							/deep/ a{
								color: #68ab86;
							}
							/deep/ a:active{
								text-decoration: underline;
							}
							/deep/ .face-message{
								margin: 0 5rpx;
								width: 42rpx;
								height: 42rpx;
								vertical-align: bottom;
								pointer-events: none;
							}
						}
						.text.sound{
							display: flex;
							align-items: center;
							.sound-icon{
								width: 40rpx;
								height: 40rpx;
								margin-right: 30rpx;
								margin-left: 0;
								background-image: url("~@/public/images/message/sound.png");
								background-size: 100%;
								background-repeat: no-repeat;
								background-position: center;
								&.playing{
									background-image: url("~@/public/images/message/sounding.gif");
								}
							}
							text{
								font-size: 28rpx;
								line-height: 28rpx;
								display: inline-block;
							}
						}
						.image{
							image, .lazy-image{
								border-radius: 10rpx;
								pointer-events: none;
							}
						}
						.video{
							position: relative;
							display: flex;
							align-items: center;
							justify-content: center;
							max-width: 500rpx;
							.video-thumb{
								border-radius: 10rpx;
							}
							.play-icon{
								width: 80rpx;
								position: absolute;
							}
						}
						.status{
							align-self: flex-end;
							margin-top: 9rpx;
							color: #B3B3B3;
							font-size: 22rpx;
							line-height: 22rpx;
						}
					}
					&.me{
						flex-direction: row-reverse;
						.right{
							margin: 0 20rpx 0 0;
							.text{
								background: #3377FF;
								color: #FFFFFF;
								a{
									color: #69dd9f;
								}
							}
							.text.sound{
								.sound-icon{
									margin-right: 0;
									margin-left: 30rpx;
									background-image: url("~@/public/images/message/sound_me.png");
									transform: rotateY(180deg);
									&.playing{
										background-image: url("~@/public/images/message/sounding_me.gif");
									}
								}
							}
						}
					}
				}
			}
		}
	}
	.foot{
		max-width: $max-width;
		margin: $pc-margin;
		background: #FFFFFF;
		position: fixed;
		bottom: 0;
		left: 0;
		right: 0;
		width: 100%;
		min-height: 96rpx;
		padding-bottom: var(--safe-area-inset-bottom);
		.input-box{
			padding: 12rpx 30rpx;
			align-items: flex-end;
			background: #FFFFFF;
			.icon{
				width: 56rpx;
				height: 72rpx;
				&.mr25{
					margin-right: 25rpx;
				}
			}
			.textarea{
				background: #F2F5FA;
				border-radius: 36rpx;
				font-size: 36rpx;
				line-height: 52rpx;
				flex: 2;
				margin: 0 25rpx;
				padding: 10rpx 36rpx;
				border: none;
				width: 450rpx;
				word-wrap:break-word;
				word-break:break-all;
				outline: none;
				overflow-y: auto;
				display: flex;
				align-items: center;
				flex-wrap: wrap;
				max-height: 364rpx;
			}
			.btn{
				background-color: limegreen;
				color: #fff;
				font-size: 30rpx;
				height: 72rpx;
				padding: 0;
				border: 0;
				width: 100rpx;
			}
			div {
				&.textarea{
					min-height: 52rpx;
				}
			}
			.send-audio{
				margin: 0 25rpx;
				width: 450rpx;
				height: 72rpx;
				background: #F2F5FA;
				border-radius: 36rpx;
				align-items: center;
				justify-content: center;
				image{
					width: 32rpx;
					height: 32rpx;
					margin-right: 20rpx;
				}
				text{
					font-size: 30rpx;
					font-weight: 500;
				}
			}
		}
		.other-box{
			align-items: center;
			background: #F2F5FA;
			.other-item{
				width: 25%;
				align-items: center;
				padding: 30rpx 0;
				image{
					width: 96rpx;
					height: 96rpx;
				}
				text{
					font-size: 24rpx;
					line-height: 24rpx;
					margin: 20rpx 0 0;
				}
			}
		}
		.face-box{
			display: flex;
			flex-direction: column;
			background: #F2F5FA;
			position: relative;
			align-items: center;
			.delete{
				position: fixed;
				bottom: var(--safe-area-inset-bottom);
				//right: 0;
				width: 68rpx;
				height: 68rpx;
				padding: 16rpx 40rpx 16rpx 16rpx;
				border-radius: 40rpx 0 0 40rpx;
				background-color: #F2F5FA;
				//background: linear-gradient(to top, rgba(242, 245, 250, 1), rgba(242, 245, 250, 0.8));
				align-self: flex-end;
			}
			.mytextarea{
				background: #F1F1F1;
				border-radius: 23rpx;
				height: 46rpx;
				font-size: 30rpx;
				line-height: 40rpx;
				flex: 2;
				margin: 0 25rpx;
				padding: 5rpx 20rpx;
				border: none;
			}
		}
	}
	.full-screen{
		position: fixed;
		bottom: 0;
		left: 0;
		right: 0;
		width: 100%;
		background-color: #000;
		padding-top: 96rpx;
		padding-bottom: var(--safe-area-inset-bottom);
		display: flex;
		flex-direction: row;
		align-items: center;
		justify-content: center;
		height: calc(100vh - 96rpx - var(--vh-offset, 0px) - var(--safe-area-inset-bottom));
		z-index: 100;
		movable-area {
			height: 100%;
			width: 100%;
		}
		movable-view image {
			width: 100%;
		}
		.pic {
			display: flex;
			align-items: center;
			justify-content: center;
			width: 100%;
			height: 100%;
			display: flex;
			background-color: #000000;

			image {
				width: 100%;
			}
		}
		.img{
			width: 100vw;
			height: 80%;
			background-repeat: no-repeat;
			background-position: center;
			background-size: 100%;
			pointer-events: none;
		}
		
		.cropper-wrap-tools {
			position: absolute;
			left: 0;
			top: 96rpx;
			width: 100%;
			display: flex;
			justify-content: space-between;
			z-index: 101;
			.cropper-wraper-cancel , .cropper-wraper-confirm {
				width: 250rpx;
				height: 88rpx;
				display: flex;
				justify-content: center;
				align-items: center;
				color: #FFFFFF;
				font-size: 32rpx;
			}
		}
	}
	.shade {
		position: fixed;
		z-index: 100;
		top: 0;
		right: 0;
		bottom: 0;
		left: 0;
		-webkit-touch-callout: none;
	
		.pop {
			position: fixed;
			z-index: 101;
			width: 200rpx;
			border-radius: 4rpx;
			box-sizing: border-box;
			font-size: 28rpx;
			text-align: left;
			color: #333;
			background-color: #fff;
			box-shadow: 0 0 5rpx rgba(0, 0, 0, 0.5);
			line-height: 80rpx;
			transition: transform 0.15s ease-in-out 0s;
			user-select: none;
			-webkit-touch-callout: none;
			transform: scale(0, 0);
	
			&.show {
				transform: scale(1, 1);
			}
	
			&>view {
				padding: 0 20rpx;
				overflow: hidden;
				text-overflow: ellipsis;
				white-space: nowrap;
				user-select: none;
				-webkit-touch-callout: none;
	
				&:active {
					background-color: #f3f3f3;
				}
			}
		}
	}
</style>
